/*=========================================================================
     This file is part of the XIOT library.

     Copyright (C) 2008-2009 EDF R&D
     Author: Kristian Sons (xiot@actor3d.com)

     This library is free software; you can redistribute it and/or modify
     it under the terms of the GNU Lesser Public License as published by
     the Free Software Foundation; either version 2.1 of the License, or
     (at your option) any later version.

     The XIOT library is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU Lesser Public License for more details.

     You should have received a copy of the GNU Lesser Public License
     along with XIOT; if not, write to the Free Software
     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
     MA 02110-1301  USA
=========================================================================*/
#ifndef X3D_X3DLOADER_H
#define X3D_X3DLOADER_H

#include <xiot/XIOTConfig.h>
#include <string>


 /*!
   
 \mainpage XIOT - The X3D I/O Toolkit library

    \section intro_sec Introduction
	The aim of this library is to provide a tool set that allows importing and exporting of X3D files.
	It is meant to be easy to integrate to third party software. The intention is to have an easy
	possibility to integrate X3D import or export functions to existing scene graphs or render systems
	like <A href="http://www.vtk.org">VTK</A> or <a href="http://www.ogre3d.org/">Ogre3D</a>.
	So XIOT does <b>not</b> provide a scene graph, no logic checking
	and no event system. The library focuses on the possibility to map an X3D description
	to an existing scene graph or event system. The logic validation has to be done during
	the mapping to the target system.

	\section platforms Platforms
	The library has been tested to compile and work on following platforms / compilers:
	<ul>
	  <li> Windows XP 32-bit / VC 9.0</li>
	  <li> Ubuntu 8.04 32-bit / gcc 4.2.4</li>
	  <li> Windows Vista 64-bit / VC 9.1</li>
	  <li> Debian Etch 64-bit / gcc 4.1.4</li>
	</ul>

    \section install Installation
	The library comes with a <a href="http://www.cmake.org/">CMake</a> configuration
	file (CMakeList.txt). CMake will generate Makefiles or projects for your favourite
	IDE. You will need CMake >= 2.6.0 to process the delivered configuration files. 

	\subsection depends Dependencies
	The XIOT library depends on tow external libraries: xercesc for parsing of XML encoded X3D files,
	and zlib for decoding of binary encoded X3D files

	\subsubsection xercesc XercesC
	To compile and run the XIOT library you will need <a href="http://xerces.apache.org/xerces-c/">Xerces-C</a>.
	The library distribution comes with a win32 and win64 version of this library.
	For all other platforms, CMake will try to find the library on your system. 
	It will complain and stop processing if it cannot find Xerces
	headers and libs. In this case you have to specify the location of Xerces manually.
	
	If you don`t have Xerces installed, you can download binary packages for serveral platforms
	<a href="http://xerces.apache.org/xerces-c/download.cgi">here</a>. On an Apt-based Linux 
	distro you can install Xerces doing something like this:
	<code>
	sudo apt-get install libxerces27 libxerces27-dev
	</code>
	The library has been tested with Xerces versions 2.7.0 and 3.0.0.

	\subsubsection zlib zlib
	The X3D-specific encoding of fields uses zlib compression i.e. for int and float arrays.

	The library distribution comes with a win32 and win64 version of this library.
	For all other platforms, CMake will try to find the library on your system. 
	It will complain and stop processing if it cannot find zlib
	headers and libs. In this case you have to specify the location of Xerces manually.

	If you don`t have zlib installed, you can find the source and links to binary packages 
	for serveral platforms <a href="http://www.zlib.net/">here</a>. On an Apt-based Linux 
	distro you can install zlib doing something like this:
	<code>
	sudo apt-get install zlib1g zlib1g-dev
	</code>
	The library has been tested with zlib version 1.2.3.

	\subsection test Tests
	The library comes with 3 simple applications to test the functionality of the library:
	<ol>
	<li><b>simpleTest</b><br/>This test application processes some nodes of an X3D file and prints out
	some attribute informations.</li>
	<li><b>shapeCounter</b><br/>This test application counts the Shape nodes in an X3D file 
	and prints out this number.</li>
	<li><b>createEventLog</b><br/>This test application logs all events generated by the 
	library to an file.</li>
	<li><b>fitest</b><br/>This test application processes a binary X3D file and outputs it's string
	representation.</li>
	</ol>
	All applications take an X3D file as input. Start the application with <code>--help</code>
	 to get information on usage. These simple test applications are a good start to learn
	how the library works.
	\section usage Usage
	The idea of this library is that you have just to provide a single instance of
	your custom XIOT::X3DNodeHandler. Best way is to derive from XIOT::X3DDefaultNodeHandler, so you have just to implement those callbacks you are interested in.
	\subsection nodecallbacks Node Callbacks
	The library generates callbacks for all existing nodes in the X3D spec. So if you want to process Shape nodes, you just override <code>startShape</code> or <code>endShape</code> depending on your aim. A simple Shape counter looks like this:
	\code
class MyShapeCounter : public XIOT::X3DDefaultNodeHandler {
	
  public:
    MyShapeCounter() { };

    virtual void startDocument() {
      _count = 0;
    }

    virtual void endDocument() {
      std::cout << "Found " << _count << " shape nodes in file";
      std::cout << std::endl;
    }

    virtual int startShape(const XIOT::X3DAttributes &attr)
    {
      _count++;
      return XIOT::CONTINUE;
    }

  protected:
    int _count;  
};
\endcode

In callback <code>startShape</code> we return XIOT::CONTINUE so the parser will continue with standard processing. You could also return XIOT::SKIP_CHILDREN since we do not expect further Shape nodes below a Shape node.
	\subsection Accessing Fields
	You get access to the X3D fields via the XIOT::X3DAttributes parameter in the start
	callbacks. The common way is first to check if a certain attribute is available and
	than to request it using the Getter methods of XIOT::X3DAttributes.
	\code
int MyNodeHandler::startMaterial(const XIOT::X3DAttributes &attr)
{	
	int index = attr.getAttributeIndex(ID::diffuseColor);
	if (index != -1)
	{
		XIOT::SFColor diffuseColor = attr.getSFColor(index);
		cout << "Diffuse Color is set as: " << diffuseColor.r << " " << diffuseColor.g << " " << diffuseColor.b << endl;
	}
	return XIOT::CONTINUE;
}
	\endcode
	Please be aware that the library does not know the corresponding datatype for a field. The internal parser will always try to convert the field (come what may). The user is in charge to request the right data type.  

	\subsection errorhandling Error Handling
	If an error occures during parsing, a XIOT::X3DParseExeption will be thrown wich contains information about the error:
\code
int start(const string &input_filename)
{
	XIOT::X3DLoader loader;
	MyNodeHandler handler;
	loader.setNodeHandler(&handler);
	try {
		loader.load(input_filename);
	} catch (XIOT::X3DParseException& e)
	{	
	  cerr << "Error while parsing file " << input_filename << ":" << endl;
	  cerr << e.getMessage() << " (Line: " << e.getLineNumber() << ", Column: " << e.getColumnNumber() << ")" << endl;
	  return 1;
	}
	return 0;
}
\endcode

	\section examples Examples
	\subsection vtkX3DImporter vtkX3DImporter
	The library comes with one more sophisticated example. It demonstrates how to import
	X3D data to the Visualization Toolkit (VTK). To build this demonstrator you will have 
	to turn on the BUILD_X3DLOADER_EXAMPLES when using CMake. This can be done using the CMake
	GUI or starting <code>cmake -i</code>. This example has dependencies to VTK. CMake will
	look for a suitable version of VTK on your system. If it does not suceed you will have to
	point to a VTK build manually. This can be done setting the VTK_DIR cache variable.
	@image html vtkX3DImporter_screen.jpg
	\subsection pvX3DReader
	<p>This module is not really an example. It demonstrates the vtkX3DImporter capabilities by
	using it inside of a <a href="http://www.paraview.org/">ParaView</a> plugin.
	The compilation and installation of the plugin is a little tricky:
	<ol>
	<li>You have to turn <code>ON</code> both options <code>BUILD_X3DLOADER_EXAMPLES</code> and
	 <code>BUILD_PARAVIEW_PLUGIN</code> in your cmake configuration.</li>
	<li>You have to specify the location of your ParaView build using <code>ParaView_DIR</code>.</li>
	<li>The ParaView you build the plugin against has to be build with shared libraries (<code>BUILD_SHARED_LIBS</code>).</li>
	<li>For your ParaView build and for the plugin GUI you need to build ParaView using QT (<code>PARAVIEW_BUILD_QT_GUI</code>).</li>
	<li>Be sure that the plugin reaches all dependent libraries on it's own. You can test this using <a href="http://kerneltrap.org/man/linux/man1/ldd.1">ldd</a> on Linux or <a href="http://www.dependencywalker.com/">depends</a> on Windows.</li>
	<li>Use the ParaView Plugin Manager to load the plugin. The you will find a X3D file filter using File->Open</li>
	</ol>
	For additional informations concerning ParaView Plugins see the ParaView <a href="http://paraview.org/Wiki/Plugin_HowTo">Plugin HowTo</a>.</p><br>
	@image html x3d_in_paraview.jpg

   * @defgroup x3dloader X3D Loader
 */
namespace XIOT {

// forward declarations
class X3DNodeHandler;

/**
 * Interface for all X3D loader implementations.
 *
 * This class contains a setter for the callback handler (X3DNodeHandler) 
 * and the function load. This function starts the
 * loading process on the file given as parameter. The generic X3DLoader implementation
 * just delegates the work to a XML-based Implementation (XMLX3DLoader) or a FI-based
 * implementation of the loader (FIX3DLoader), depending on the extension.
 * An example on how to use the loader:
 * <pre>
 * X3DLoader loader;
 * loader.setNodeHandler(new MyShapeCounter());
 * loader.load("Example.x3db"); // X3DFILoader will be used internally
 * </pre>
 * @ingroup x3dloader
 */
class XIOT_EXPORT X3DLoader
{
public:
  /// Constructor.
  X3DLoader();
  /// Destructor.
  virtual ~X3DLoader();
  
  /**
   * Loads an X3D scene graph from the file.
   *
   * @param fileName Absolute path to the file. Make sure that the
   * path is valid.
   * @param fileValidation If <code>true</code>, then the file will be 
   * verified and messages will be written if the file is invalid. 
   * @return <code>true</code>, if the loading process was successful
   */
  bool load(const char* fileName, bool fileValidation = false) const;
  
  /**
   * Sets the X3DNodeHandler which processes the callbacks. If there is already
   * a handler, it will be replaced. 
   * @warning The loader will not delete the handler. Please make shure the 
   * user of the library will delete the handler when the loading process 
   * has finished.
   * @param handler The handler to use for callbacks
   */
  void setNodeHandler(X3DNodeHandler *handler);
  
protected:
  /// Handler.
  X3DNodeHandler *_handler;
};

}

#endif
